home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The 640 MEG Shareware Studio 2
/
The 640 Meg Shareware Studio CD-ROM Volume II (Data Express)(1993).ISO
/
prog
/
yamp2.zip
/
VIRTOP.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-16
|
45KB
|
1,628 lines
/*
YAMP - Yet Another Matrix Program
Version: 1.2
Author: Mark Von Tress, Ph.D.
Date: 01/23/92
Copyright(c) Mark Von Tress 1992
Portions of this code are (c) 1991 by Allen I. Holub and are used by
permission
DISCLAIMER: THIS PROGRAM IS PROVIDED AS IS, WITHOUT ANY
WARRANTY, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
TO FITNESS FOR A PARTICULAR PURPOSE. THE AUTHOR DISCLAIMS
ALL LIABILITY FOR DIRECT OR CONSEQUENTIAL DAMAGES RESULTING
FROM USE OF THIS PROGRAM.
*/
#include "virt.h"
/////////////////// matrix functions ---- non-member functions
int Setwid(int w )
{
static int wid=6;
wid = ( w < 0 ) ? wid : w;
return wid;
}
int Setdec ( int d )
{
static int dec = 3;
dec = ( d < 0 ) ? dec : d;
if ( d >= Getwid() ) dec = Getwid() - 1;
dec = (dec <=0 ) ? 0 : dec;
return dec;
}
int Getwid( void )
{
static int wid=6;
wid = Setwid( -1 );
return wid;
}
int Getdec(void )
{
static int dec=3;
dec = Setdec( -1 );
return dec;
}
VMatrix &Reada( char *fid) /* this reads an ascii matrix */
{
unsigned int chh[MAXCHARS],*chc;
int i=0,j=0,x1=0,x2=0;
FILE *file;
char mname[MAXCHARS];
float x=0;
file = fopen( fid, "r");
if( !file ) Dispatch->Nrerror("READA: error while opening file");
for( i = 0; i<80; i++) chh[i] = 0;
i = 0;
do { /* read until first carriage return */
j = fgetc( file );
chh[i] = j;
i++;
} while( j != ((int) 0x0A) && !ferror(file) && (i<80)) ;
if ( ferror(file) ) Dispatch->Nrerror("READA: error while reading matrix name");
chh[i] = (int) '\0'; /* null terminate the string */
if ( chh[0] != (int) 0x0A ) {
strcpy( mname,((const char *) chh ));
chc = chh;
for(j = 1; j<i-1; j++) strcat( mname, (( const char *) (++chc) ));
}
else
{
strcpy(mname," ");
}
fscanf(file,"%d%d",&x1,&x2);
VMatrix *mat =new VMatrix(mname,x1,x2);
for( i=1; i<=x1; i++){
for( j=1; j<=x2; j++){
fscanf(file,"%f",&x);
mat->M(i,j) = (double) x ;
}
}
fclose( file );
Dispatch->Push( *mat );
delete mat;
return Dispatch->ReturnMat();
} /* reada */
VMatrix &Readb(char *fid) /* this reads an binary matrix */
{
int i=0,j=0,x1=0,x2=0;
FILE *file;
char name[MAXCHARS];
double x=0;
file = fopen( fid, "rb");
if( !file ) Dispatch->Nrerror("READB: error while opening file");
fread(&i, sizeof(int), 1, file);
fgets( name, (i+1), file);
fread(&x1, sizeof(int), 1, file);
fread(&x2, sizeof(int), 1, file);
VMatrix *mat = new VMatrix( name,x1,x2);
for( i=1; i<=x1; i++){
for( j=1; j<=x2; j++){
fread(&x, sizeof(double), 1, file);
mat->M(i,j) = x ;
}
}
fclose( file );
Dispatch->Push( *mat );
delete mat;
return Dispatch->ReturnMat();
} /* readb */
void Writea(char *fid, VMatrix &mat) /* write a matrix in an ascii file */
{
int i,j;
FILE *file;
file = fopen( fid, "w" );
if ( !file ) Dispatch->Nrerror("WRITEA: unable to open file");
mat.Garbage("Writea");
fprintf(file,"%s\n", mat.StringAddress() );
fprintf(file,"%d %d \n", mat.r, mat.c );
for( i=1; i<= mat.r; i++){
for(j=1; j<= mat.c; j++)
fprintf(file,"%lf ",mat.m(i,j));
fprintf(file,"\n");
}
fclose(file);
} /* writea */
void heapsort( VMatrix &a )
// void svsort(n,v1,v2)
//* sort uniform[0,1]'s in v1 and swap integers in
// v2 as uniforms are swapped */
// int n,v2[];
// double v1[];
{
int n=a.r;
int s0,s1,s2,s3,s4,s5,ts,s4m1,s5m1;
double t1;
s0=s1= n; /* Shell-Metzger sort, PC-World, May 1986 */
s1 /= 2;
while(s1 > 0) {
s2=s0-s1;
for(s3=1; s3<=s2; s3++) {
s4=s3;
while (s4>0){
s5=s4+s1;
s4m1=s4;
s5m1=s5;
if ( a.m(s4m1,1) > a.m(s5m1,1) ){
t1=a.m(s4m1,1);
a.M(s4m1,1)=a.m(s5m1,1);
a.M(s5m1,1)=t1;
ts=a.m(s4m1,2);
a.M(s4m1,2)=a.m(s5m1,2);
a.M(s5m1,2)=ts;
s4=s4-s1;
}
else{
s4=0;
}
}
}
s1 /=2;
}
}
VMatrix &MSort(VMatrix &a, int col, int order)
{
a.Garbage();
VMatrix *sorted = new VMatrix("sorted(",a.r,a.c);
if( !order ){
// sort column col, then reorder other rows
VMatrix *temp = new VMatrix("temp",a.r,2);
for (int i=1; i<= a.r; i++ ) {
temp->M(i,1) = a.m(i,col);
temp->M(i,2) = (double)i;
}
heapsort( *temp );
for( i=1; i<=a.r; i++){
for( int j=1; j<=a.c; j++)
sorted->M( i,j ) = a.m( ((int)temp->m(i,2)), j );
}
delete temp;
}
else{
// sort row col, then reorder other columns
VMatrix *temp = new VMatrix("temp",a.c,2);
for (int i=1; i<= a.c; i++ ) {
temp->M(i,1) = a.m(col,i);
temp->M(i,2) = (double) i;
}
heapsort( *temp );
for( i=1; i<=a.c; i++){
for( int j=1; j<=a.r; j++)
sorted->M( j,i ) = a.m(j, ((int)temp->m(i,2)) );
}
delete temp;
}
strtype name = sorted->Getname(*sorted);
name = name+a.Getname(a)+")";
sorted->Nameit(name);
Dispatch->Push(*sorted);
delete sorted;
return Dispatch->ReturnMat();
}
VMatrix &Submat(VMatrix &a, int r, int c, int lr, int lc )
/* extract a submatrix of a into b*/
{
a.Garbage("Submat");
if( (r > a.r ) || ( c > a.c) )
a.Nrerror( "SUBMAT: index out of range");
VMatrix *b = new VMatrix( "b", r-lr+1, c-lc+1);
strtype temp = a.Getname(a);
b->Nameit( temp );
int r2 = r-lr+1;
int c2 = c-lc+1;
for(int i=1; i<=r2; i++){
for(int j=1; j<=c2; j++) b->M(i,j) = a.m(lr-1+i,lc-1+j);
}
Dispatch->Push(*b);
delete b;
return Dispatch->ReturnMat();
} /* submat */
VMatrix &Ch(VMatrix &a,VMatrix &b ) /* horizontal concatination */
{
a.Garbage("Ch");
b.Garbage("Ch");
int adim = a.c;
int bdim = b.c;
int k = adim+bdim;
if ( a.r != b.r)
a.Nrerror("CH: matrices have different number of rows");
VMatrix *c = new VMatrix("(",a.r, k);
if( !c ) a.Nrerror("CH: failed to create temp storage");
strtype mname = c->Getname(*c)+a.Getname(a)+"||"+b.Getname(b)+")";
c->Nameit( mname );
for ( int i=1; i <= a.r; i++){
for(int j=1; j <= a.c; j++)
c->M(i,j) = a.m(i,j);
}
int ii;
for ( i=1, ii=1; i<=b.r; i++, ii++){
for( int j=1, jj=1; j<=b.c; j++, jj++) c->M(ii,jj+a.c) = b.m(i,j);
}
Dispatch->Push(*c);
delete c;
return Dispatch->ReturnMat();
} /* ch */
VMatrix &Cv(VMatrix &a,VMatrix &b ) /* vertical concatination */
{
a.Garbage("Cv");
b.Garbage("Cv");
int adim = a.r;
int bdim = b.r;
int k = adim + bdim;
if ( a.c != b.c)
a.Nrerror("CV: matrices have different number of columns");
VMatrix *c = new VMatrix("(",k, a.c);
strtype mname = c->Getname(*c)+a.Getname(a)+"//"+b.Getname(b)+")";
c->Nameit( mname );
for ( int i= 1; i <= a.r; i++){
for( int j= 1; j <= a.c; j++)
c->M(i,j) = a.m(i,j);
}
int ii;
for ( i=1, ii=1; i<=b.r; i++, ii++){
for( int j=1, jj=1; j<=b.c; j++, jj++) c->M(ii+a.r,jj) = b.m(i,j);
}
Dispatch->Push(*c);
delete c;
return Dispatch->ReturnMat();
} /* cv */
////////////////// math funtions
VMatrix& Tran(VMatrix &ROp )
{
ROp.Garbage("Tran");
VMatrix *temp = new VMatrix("t",ROp.c,ROp.r);
strtype newname = temp->Getname(ROp);
for( int i=1; i<=ROp.r; i++){
for( int j=1; j<=ROp.c; j++) temp->M(j,i) = ROp.m(i,j);
}
newname = newname + "'";
temp->Nameit( newname ) ;
Dispatch->Push(*temp);
delete temp;
return Dispatch->ReturnMat();
}
VMatrix& Mexp(VMatrix &ROp )
{
// take exponent of all elements
ROp.Garbage("Mexp");
VMatrix *temp = new VMatrix("exp(",ROp.r,ROp.c);
for( int i=1; i<=ROp.r; i++){
for( int j=1; j<=ROp.c; j++) temp->M(i,j) = exp(ROp.m(i,j));
}
strtype newname = temp->Getname(*temp) + ROp.Getname(ROp) + ")";
temp->Nameit( newname ) ;
Dispatch->Push(*temp);
delete temp;
return Dispatch->ReturnMat();
}
VMatrix& Mabs(VMatrix &ROp )
{
// take absolute values of all elements
ROp.Garbage("Mabs");
VMatrix *temp = new VMatrix("abs(",ROp.r,ROp.c);
for( int i=1; i<=ROp.r; i++){
for( int j=1; j<=ROp.c; j++) temp->M(i,j) = fabs(ROp.m(i,j));
}
strtype newname = temp->Getname(*temp) + ROp.Getname(ROp) + ")";
temp->Nameit( newname ) ;
Dispatch->Push(*temp);
delete temp;
return Dispatch->ReturnMat();
}
VMatrix& Mlog(VMatrix &ROp )
{
// take logarithm of all elements
ROp.Garbage("Mlog");
VMatrix *temp = new VMatrix("log(",ROp.r,ROp.c);
for( int i=1; i<=ROp.r; i++){
for( int j=1; j<=ROp.c; j++) {
double R = ROp.m(i,j);
temp->M(i,j) = ( R > 0.0 ) ? log( R ) :
Dispatch->Nrerror("Mlog: zero or negative argument to log");
}
}
strtype newname = temp->Getname(*temp) + ROp.Getname(ROp) + ")";
temp->Nameit( newname ) ;
Dispatch->Push(*temp);
delete temp;
return Dispatch->ReturnMat();
}
VMatrix& Msqrt(VMatrix &ROp )
{
// take sqrt of all elements
ROp.Garbage("Msqrt");
VMatrix *temp = new VMatrix("sqrt(",ROp.r,ROp.c);
for( int i=1; i<=ROp.r; i++){
for( int j=1; j<=ROp.c; j++) {
double R = ROp.m(i,j);
temp->M(i,j) = ( R >= 0.0 ) ? sqrt( R ) :
Dispatch->Nrerror("Msqrt: zero or negative argument to sqrt");
}
}
strtype newname = temp->Getname(*temp) + ROp.Getname(ROp) + ")";
temp->Nameit( newname ) ;
Dispatch->Push(*temp);
delete temp;
return Dispatch->ReturnMat();
}
double Trace( VMatrix &ROp )
{
ROp.Garbage("Trace");
double trace = 0;
if( ROp.r != ROp.c )
ROp.Nrerror("Trace: matrix not square in trace");
for( int i=1; i<=ROp.r; i++) trace += ROp.m(i,i);
return trace;
}
VMatrix& Ident(int n )
{
VMatrix *temp = new VMatrix("I(",n,n);
for( int i=1; i<=n; i++) {
for( int j=1; j<=n; j++) temp->M(i,j) =(i == j) ? 1.0 : 0.0;
}
char buffer[MAXCHARS]={'\0'};
gcvt( ((double) n), NDECS, buffer);
strtype string = buffer;
string = temp->Getname(*temp)+string+")";
temp->Nameit( string );
Dispatch->Push(*temp);
delete temp;
return Dispatch->ReturnMat();
}
VMatrix& Helm( int n )
{
VMatrix *temp = new VMatrix("Helm(",n,n);
for( int i=1; i<=n; i++) {
for( int j=1; j<=n; j++){
double d = 1.0/sqrt( (double) n );
double den = ( j>1 ) ? 1.0 / sqrt( (double) j*(j-1) ) : d;
if( j>1 && j<i ) d = 0;
if( j>1 && j==i) d = - den * ( (double ) (j-1) );
if( j>1 && j>i ) d = den;
temp->M(i,j) = d;
}
}
char buffer[MAXCHARS]={'\0'};
gcvt( ((double) n), NDECS, buffer);
strtype string = buffer;
string = temp->Getname(*temp)+string+")";
temp->Nameit( string );
Dispatch->Push(*temp);
delete temp;
return Dispatch->ReturnMat();
}
VMatrix& Fill(int r, int c, double d )
{
VMatrix *temp = new VMatrix("j",r,c);
for( int i=1; i<=r; i++) {
for( int j=1; j<= c; j++) temp->M(i,j) = d;
}
Dispatch->Push(*temp);
delete temp;
return Dispatch->ReturnMat();
}
VMatrix& Index( int lower, int upper, int step)
{
if( step == 0 ) Dispatch->Nrerror("Index: step is zero");
int cnter = 0;
if( lower < upper ){
for( int i=lower; i<= upper; cnter++, i += step );
}
else{
for( int i=upper; i>= lower; cnter++, i += step );
}
if (cnter == 0)
Dispatch->Nrerror("Index: trying to allocate a matrix with zero rows");
VMatrix *temp = new VMatrix("Index",cnter, 1);
cnter = 1;
if( lower < upper ){
for( int i=lower; i<= upper; i += step )
temp->M( cnter++, 1) = (double) i;
}
else{
for( int i=upper; i>= lower; i += step )
temp->M( cnter++, 1) = (double) i;
}
Dispatch->Push( *temp );
delete temp;
return Dispatch->ReturnMat();
}
VMatrix& Sweep( int k1, int k2, VMatrix& ROp) /* sweep out a row */
{
long double eps=ZERO, d;
int i,j,k,n, it;
ROp.Garbage("Sweep");
if (ROp.r != ROp.c ) ROp.Nrerror("SWEEP: matrix a is not square");
n = ROp.r;
if (k2 < k1 ){ k=k1; k1=k2; k2=k;}
for ( k=k1; k<=k2; k++){
if( fabs(ROp.m(k,k)) < eps )
for( it = 1; it<= n; it++){
ROp.M(it,k) = 0;
ROp.M(k,it) = 0;
}
else {
d = 1.0/ROp.m(k,k);
ROp.M(k,k) = d;
for (i=1; i<=n; i++) {if ( i != k )
ROp.M(i,k) = ROp.m(i,k)*(double) -d;}
for (j=1; j<=n; j++) {if ( j != k )
ROp.M(k,j) = ROp.m(k,j)*(double) d;}
for (i=1; i<=n; i++) {
if( i != k ) {
for(j =1; j<=n; j++) {
if (j != k )
ROp.M(i,j) = ROp.m(i,j)+(ROp.m(i,k))*(ROp.m(k,j))/d;
}
}
}
}
}
strtype newname = "sweep(";
newname = newname + ROp.Getname(ROp) + ")";
ROp.Nameit( newname );
Dispatch->Push( ROp );
return Dispatch->ReturnMat();
}/*sweep*/
VMatrix& Inv( VMatrix &ROp ) /*matrix inversion using sweep */
{
struct mat *b;
ROp.Garbage("Inv");
Dispatch->Inclevel();
if( ROp.c != ROp.r ) ROp.Nrerror("INVERSE: matrix a not square");
strtype newname = "invs(";
newname = newname + ROp.Getname(ROp) + ")";
VMatrix *temp = new VMatrix("t",ROp.c,ROp.r);
*temp = ROp;
*temp = Sweep(1, temp->r, *temp);
temp->Nameit( newname );
Dispatch->Push( *temp );
delete temp;
return Dispatch->DecReturn();
} /* inverse */
VMatrix &Kron(VMatrix &a, VMatrix &b)
{
a.Garbage("Kron");
b.Garbage("Kron");
int cr = a.r*b.r;
int cc = a.c*b.c;
VMatrix *c = new VMatrix( "(", cr, cc);
strtype mname = c->Getname(*c)+a.Getname(a)+"@"+b.Getname(b)+")";
c->Nameit( mname );
for(int i=1; i<=a.r; i++){
for(int j=1; j<=a.c; j++){
for(int k=1; k<=b.r; k++ ){
for(int l=1; l<=b.c; l++){
c->M((i-1)*b.r+k,(j-1)*b.c+l) = a.m(i,j)*b.m(k,l);
}
}
}
}
Dispatch->Push(*c);
delete c;
return Dispatch->ReturnMat();
} /* kron */
void Pivot(VMatrix &Data, int RefRow,
double &Determ,enum boolean &DetEqualsZero)
{
DetEqualsZero = TTRUE;
int NewRow = RefRow;
while (DetEqualsZero && (NewRow < Data.r) ) {
NewRow++;
if (fabs(Data.m(NewRow, RefRow)) > ZERO) {
for(int i=1; i<=Data.r; i++){
double temp = Data.m(NewRow,i);
Data.M(NewRow,i)=Data.m(RefRow,i);
Data.M(RefRow,i) = temp;
}
DetEqualsZero = FFALSE;
Determ = -Determ; /* row swap adjustment to det */
}
}
}
double Det( VMatrix &Datain)
{
Datain.Garbage("Det");
if( Datain.r == Datain.c ){
Dispatch->Inclevel();
int Dimen = Datain.r;
VMatrix *Data = new VMatrix("data",Dimen,Dimen);
*Data= Datain;
double Determ = 1;
long double Coef;
int Row, RefRow = 0;
enum boolean DetEqualsZero = FFALSE;
while (!(DetEqualsZero) && (RefRow < Dimen - 1) ) {
RefRow++;
if (fabs(Data->m(RefRow, RefRow)) < ZERO)
Pivot(*Data, RefRow, Determ, DetEqualsZero);
if (!(DetEqualsZero))
for (Row = RefRow + 1; Row <= Dimen; Row++)
if (fabs(Data->m(Row, RefRow)) > ZERO) {
Coef = -((long double)Data->m(Row, RefRow)) /
((long double)Data->m(RefRow, RefRow));
for( int i=1; i<=Dimen; i++)
Data->M(Row,i) = Data->m(Row,i) +
(double)(Coef*((long double)Data->m(RefRow,i)));
}
Determ *= Data->m(RefRow, RefRow);
}
Determ =( DetEqualsZero ) ? 0 : Determ * Data->m(Dimen, Dimen);
delete Data;
Dispatch->Declevel();
return Determ;
}
else Datain.Nrerror("Det: Matrix is not square\n");
}
//--------------- cholesky decomposition ----------------------
// ROp is symmetric, returns upper triangular S where ROp = S'S
//-------------------------------------------------------------
#define EPS 1.0e-7
VMatrix& Cholesky(VMatrix& ROp)
{
int nr = ROp.r;
ROp.Garbage("Cholesky");
for( int i=1; i<=nr; i++){
for( int j=1; j< i; j++)
if( fabs( ROp.m(i,j) - ROp.m(j,i) ) > EPS )
Dispatch->Nrerror("Cholesky: Input matrix is not symmetric");
}
VMatrix *temp = new VMatrix();
*temp = Fill(nr,nr,0.0);
for ( i=1; i<=nr; i++){
for (int j = i; j<=nr; j++){
double sum = 0.0;
for (int k=1 ; k < i; k++) {
sum += temp->m(k,i) * temp->m(k,j);
}
if (i==j) temp->M(i,j) = ( ROp.m(i,j) < sum ) ?
Dispatch->Nrerror("Cholesky: negative pivot") :
sqrt(ROp.m(i,j) - sum);
else temp->M(i,j) = ( fabs(temp->m(i,i)) < EPS ) ?
Dispatch->Nrerror("Cholesky: zero or negative pivot") :
(ROp.m(i,j) - sum) / temp->m(i,i);
}
}
strtype newname = "half(";
newname = newname + ROp.Getname(ROp) + ")";
temp->Nameit( newname );
Dispatch->Push(*temp);
delete temp;
return Dispatch->ReturnMat();
}
void QR( VMatrix& ROp, VMatrix& Q, VMatrix& R, boolean makeq)
{
ROp.Garbage("QR");
Q.Garbage("QR");
R.Garbage("QR");
Dispatch->Inclevel();
int r=ROp.r;
int c=ROp.c;
Q = ROp;
R = Fill(c,c,0.0);
double s;
for(int j=1; j<=c; j++){
double sigma = 0.0;
for( int i=j; i<=r; i++) sigma += Q.m(i,j)*Q.m(i,j);
if ( fabs( sigma) <= 1.0e-10 ) Dispatch->Nrerror("QR: singular X");
R.M(j,j) = s = ( Q.m(j,j) < 0 ) ? sqrt( sigma ) : -sqrt( sigma );
double beta = 1.0/(s*Q.m(j,j)-sigma);
Q.M(j,j) = Q.m(j,j) - s;
for(int k = j+1; k<=c; k++){
double sum = 0.0;
for( int i=j; i<=r; i++) sum += Q.m(i,j)*Q.m(i,k);
sum *= beta;
for( i=j; i<=r; i++) Q.M(i,k) = Q.m(i,k) + Q.m(i,j)*sum;
R.M(j,k) = Q.m(j,k);
}
}
if ( makeq ) Q = ROp*Ginv(R);
Q.Nameit("Q");
R.Nameit("R");
Dispatch->Declevel();
}
#undef EPS
//------------------- Singular Valued Decomposition ----------
// from EISPACK SVD
//------------------------------------------------------------
void svdtemp(VMatrix &a, VMatrix &w, boolean matu, VMatrix &u,
boolean matv, VMatrix &v, int &ierr, VMatrix &rv1)
{
Dispatch->Inclevel();
a.Garbage("SVD");
w.Garbage("SVD");
u.Garbage("SVD");
v.Garbage("SVD");
rv1.Garbage("SVD");
int m = a.r;
int n = a.c;
int i,j,k,l,ii,i1,kk,k1,ll,l1,its,mn;
// VMatrix a("a",m,n),w("w",n,1),
// u("u",m,m),v("v",n,n),rv1("rv1",n,1);
double c,f,g,h,s,x,y,z,eps,scale,machep,fss;
// boolean matu,matv;
// ********** Machep is a machine dependent parameter specifying
// the relative precision of floatin point aritmetic.
//
// **************
machep = pow(16.0,(-5.0));
ierr = 0;
u = a;
// ********householder reduction to bi diagonal form ********
g=0.0;
scale=0.0;
x=0.0;
for( i=1; i<=n; i++){
l=i+1;
rv1.M(i,1)=scale*g;
g=0.0;
s=0.0;
scale=0.0;
if (i > m) goto l210;
for (k=i; k<=m; k++) scale += fabs(u.m(k,i));
if (scale == 0.0) goto l210;
for( k=i; k <= m; k++){
u.M(k,i)=u.m(k,i)/scale;
s += u.m(k,i)*u.m(k,i);
}
f=u.m(i,i);
g=-(( f >= 0.0 ) ? fabs( sqrt(s) ) : -fabs(sqrt(s)));
h=f*g-s ;
u.M(i,i)=f-g;
if (i==n) goto l190;
for( j=l; j<=n; j++){
s=0.0;
for(k=i; k<=m; k++) s += u.m(k,i)*u.m(k,j);
f=s/h;
for(k=i; k<=m; k++) u.M(k,j)=u.m(k,j)+f*u.m(k,i);
}
l190: for( k=i; k<=m; k++) u.M(k,i)=scale*u.m(k,i);
l210: w.M(i,1)=scale*g;
g=0.0;
s=0.0;
scale=0.0;
if(i>m || i==n) goto l290;
for( k=l; k<=n; k++) scale += fabs(u.m(i,k));
if (scale == 0.0) goto l290;
for(k=l; k<=n; k++){
u.M(i,k) =u.m(i,k)/scale;
s += u.m(i,k)*u.m(i,k);
}
f=u.m(i,l);
g=-( (f >= 0.0) ? fabs(sqrt(s)): -fabs(sqrt(s)) );
h=f*g-s;
u.M(i,l)=f-g;
for( k=l; k<=n; k++) rv1.M(k,1) = u.m(i,k)/h;
if(i == m) goto l270;
for( j=l; j<=m; j++){
s=0.0;
for(k=l; k<=n; k++) s+= u.m(j,k)*u.m(i,k);
for(k=l; k<=n; k++) u.M(j,k)=u.m(j,k)+s*rv1.m(k,1);
}
l270: for( k=l; k<=n; k++ ) u.M(i,k)=scale*u.m(i,k);
l290: x = ( x > fabs(w.m(i,1))+fabs(rv1.m(i,1))) ? x :
fabs(w.m(i,1))+fabs(rv1.m(i,1)) ;
}
// ********** accumulation of right-hand transformations ********
if (!matv) goto l410;
for( ii=1; ii<=n; ii++){
i=n+1-ii;
if(i == n) goto l390;
if(g == 0.0) goto l360;
// double division avoids possible underflow
for(j=l; j<=n; j++) v.M(j,i) =(u.m(i,j)/u.m(i,l))/g;
for( j=l; j<=n; j++){
s=0.0;
for(k=l; k<=n; k++) s+=u.m(i,k)*v.m(k,j);
for(k=l; k<=n; k++) v.M(k,j)=v.m(k,j)+s*v.m(k,i);
}
l360: for( j=l; j<=n; j++){
v.M(i,j)=0.0;
v.M(j,i)=0.0;
}
l390: v.M(i,i)=1.0;
g=rv1.m(i,1);
l=i;
}
// *************accumulation of left-hand transformations
l410: if (!matu) goto l510;
// ************* for i= min(m,n) step -1 until 1 do ******
mn=n;
if (m<n)mn=m;
for(ii=1; ii<=mn; ii++){
i=mn+1-ii;
l=i+1;
g=w.m(i,1);
if(i==n) goto l430;
for(j=l; j<=n; j++) u.M(i,j)=0.0;
l430: if (g == 0.0) goto l475;
if (i==mn) goto l460;
for(j=l; j<=n; j++){
s=0.0;
for(k=l;k<=m; k++) s+=u.m(k,i)*u.m(k,j);
// double division avoids possible underflow
f=(s/u.m(i,i))/g;
for(k=i; k<=m; k++) u.M(k,j)=u.m(k,j)+f*u.m(k,i);
}
l460: for(j=i; j<=m; j++) u.M(j,i)=u.m(j,i)/g;
goto l490;
l475: for(j=i; j<=m; j++) u.M(j,i)=0.0;
l490: u.M(i,i)=u.m(i,i)+1.0;
}
// ********** diagonalization of the bidiagonal form ***********
l510: eps=machep*x;
// ********** for k=n step -1 until 1 do ***********************
for(kk=1; kk<=n; kk++){
k1=n-kk;
k=k1+1;
its=0;
// ********** test for splitting .**********
// for l=k step -1 until 1 do
l520: for( ll=1; ll <= k; ll++){
l1=k-ll;
l=l1+1;
if (fabs(rv1.m(l,1))<=eps) goto l565;
// rv1(1) is always zero, so there is no exit
// through the bottom of the loop *********
if (fabs(w.m(l1,1))<=eps) goto l540;
}
// ************* cancellation of rv1(l) if l greater than 1******
l540: c=0.0;
s=1.0;
for( i=l; i<=k; i++){
f=s*rv1.m(i,1);
rv1.M(i,1)=c*rv1.m(i,1);
if (fabs(f) <= eps) goto l565;
g=w.m(i,1);
h=sqrt(f*f+g*g);
w.M(i,1)=h;
c=g/h;
s=-f/h;
if(matu){ //go to 560
for( j=1; j<=m; j++){
y=u.m(j,l1);
z=u.m(j,i);
u.M(j,l1)=y*c +z*s;
u.M(j,i)=-y*s +z*c;
}
}
}
// ************** test for convergence ********************
l565: z=w.m(k,1);
if( l==k) goto l650;
// *************** if shift from bottom 2 by 2 minor *******
if (its == 30) goto l1000;
its=its+1;
x=w.m(l,1);
y=w.m(k1,1);
g=rv1.m(k1,1);
h=rv1.m(k,1);
f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
g=sqrt(f*f+1.0);
fss = ( f >= 0.0)? fabs(g):-fabs(g);
f=((x-z)*(x+z)+h*(y/(f+fss)-h))/x;
// **************** next qr transformation ***************
c=1.0;
s=1.0;
//
for(i1=l; i1<=k1; i1++){
i=i1+1;
g=rv1.m(i,1);
y=w.m(i,1);
h=s*g;
g=c*g;
z=sqrt(f*f+h*h);
rv1.M(i1,1)=z;
c=f/z;
s=h/z;
f=x*c+g*s;
g=-x*s+g*c;
h=y*s;
y=y*c;
if (matv){ // goto l575;
for( j=1; j<=n; j++){
x=v.m(j,i1);
z=v.m(j,i);
v.M(j,i1)=x*c+z*s;
v.M(j,i)=-x*s+z*c;
}
}
z=sqrt(f*f+h*h);
w.M(i1,1)=z;
// ************ rotation can be arbitrary if z is zero *******
if (z != 0.0){ // goto l580;
c=f/z;
s=h/z;
}
// l580:
f=c*g +s*y;
x=-s*g +c*y ;
if(matu){ //goto l600;
for( j=1; j<=m; j++){
y=u.m(j,i1);
z=u.m(j,i);
u.M(j,i1)=y*c+z*s;
u.M(j,i)=-y*s+z*c;
}
}
l600: x=x;} //continue
rv1.M(l,1)=0.0;
rv1.M(k,1)=f;
w.M(k,1)=x;
goto l520;
// ************** convergence **************
l650: if(z >= 0.0) goto l700;
// ************* w(k) is made non-negative *********
w.M(k,1)=-z;
if (!matv) goto l700;
for( j=1; j<=n; j++) v.M(j,k)=-v.m(j,k);
l700: x=x;}
ierr = 0;
Dispatch->Declevel();
return;
// ***************** set error -- no convergence to a
// singular value after 30 iterations
l1000: ierr=k;
Dispatch->Declevel();
return;
}
int Svd( VMatrix &A, VMatrix &U, VMatrix &S, VMatrix &V,
boolean makeu, boolean makev)
{
Dispatch->Inclevel();
A.Garbage("SVD");
VMatrix aa, uu, ss, vv, rv1;
int ierr = 0;
if( A.r < A.c ) aa = Tran(A);
else aa = A;
uu = Fill( aa.r, aa.r, 0.0);
vv = Fill( aa.c, aa.c, 0.0);
ss = Fill( aa.c, 1, 0.0);
rv1= Fill( aa.c, 1, 0.0);
svdtemp( aa, ss, makeu, uu, makev, vv, ierr, rv1);
if( A.r < A.c ) {
if( makeu ) U = vv;
if( makev ) V = uu;
} else {
if( makeu ) U = uu;
if( makev ) V = vv;
}
S = ss;
Dispatch->Declevel();
return ierr;
}
//---------------- end svd ------------------------------------
VMatrix& Ginv( VMatrix& ROp )
{
ROp.Garbage("Ginv");
Dispatch->Inclevel();
VMatrix *u=new VMatrix;
VMatrix *s=new VMatrix;
VMatrix *v=new VMatrix;
VMatrix *g=new VMatrix;
Svd( ROp, *u, *s, *v);
for( int i=1; i<=s->r; i++){
double t=s->m(i,1);
s->M(i,1) = ( fabs(t) <= 1.0e-10) ? 0.0 : 1.0/t;
}
*g = *v *Diag(*s)*Tran(*u);
strtype newname = "ginv(";
newname = newname + ROp.Getname(ROp) + ")";
g->Nameit( newname );
Dispatch->Push( *g );
delete u;
delete s;
delete v;
delete g;
return Dispatch->DecReturn();
}
//-------------------------- fft ------------------------------
// de Boor (1980) SIAM J SCI. STAT. COMPUT. V1 no 1, pp 173-178
// and NewMat by R. G. Davies a C++ matrix Package
//-------------------------------------------------------------
static void cossin(int n, int d, double& c, double& s)
// calculate cos(twopi*n/d) and sin(twopi*n/d)
// minimise roundoff error
{
long n4 = n * 4;
int sector = (int)floor( (double)n4 / (double)d + 0.5 );
n4 -= sector * d;
if (sector < 0) sector = 3 - (3 - sector) % 4; else sector %= 4;
double ratio = 1.5707963267948966192 * (double)n4 / (double)d;
switch (sector)
{
case 0: c = cos(ratio);
s = sin(ratio);
break;
case 1: c = -sin(ratio);
s = cos(ratio);
break;
case 2: c = -cos(ratio);
s = -sin(ratio);
break;
case 3: c = sin(ratio);
s = -cos(ratio);
break;
}
}
static void fftstep(VMatrix &AB, VMatrix &XY,
int after, int now, int before)
{
int gamma = after * before;
int delta = now * after;
double r_arg = 1.0, i_arg = 0.0;
int x = 1;
int m = AB.r - gamma;
for (int j = 0; j < now; j++){
int a = 1;
int x1 = x;
x += after;
for (int ia = 0; ia < after; ia++){
// generate sins & cosines explicitly rather than iteratively
// for more accuracy; but slower
cossin(-(j*after+ia), delta, r_arg, i_arg);
int a1 = a++;
int x2 = x1++;
if (now==2){
int ib = before;
while (ib--){
int a2 = m + a1;
a1 += after;
double r_value = AB.m(a2,1);
double i_value = AB.m(a2,2);
XY.M(x2,1) = r_value*r_arg - i_value*i_arg + AB.m(a2-gamma,1);
XY.M(x2,2) = r_value*i_arg + i_value*r_arg + AB.m(a2-gamma,2);
x2 += delta;
}
}
else {
int ib = before;
while (ib--){
int a2 = m + a1;
a1 += after;
double r_value = AB.m(a2,1);
double i_value = AB.m(a2,2);
int in = now-1;
while (in--){
a2 -= gamma;
double temp = r_value;
r_value = r_value*r_arg - i_value*i_arg + AB.m(a2,1);
i_value = temp*i_arg + i_value*r_arg + AB.m(a2,2);
}
XY.M(x2,1) = r_value;
XY.M(x2,2) = i_value;
x2 += delta;
}
}
}
}
}
VMatrix& Fft( VMatrix &ROp, boolean INZEE )
// if INZEE == TTRUE then calculate fft
// if INZEE == FFALSE then calculate inverse fft
{
ROp.Garbage("FFT");
if( ROp.c > 2 ) Dispatch->Nrerror("FFT: Input has more than two columns");
int n = ROp.r; // length of arrays
const int nextmx = 26;
int prime[26] = { 2,3,5,7,11,13,17,19,23,29,31,37,
41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83,
89, 97, 101 };
int after = 1;
int before = n;
int next = 0;
boolean inzee = TTRUE;
Dispatch->Inclevel();
VMatrix *AB = new VMatrix("AB",n,2);
VMatrix *XY = new VMatrix("XY",n,2);
if( ROp.c == 1 ){
for( int i=1; i<=n; i++){
AB->M(i,1) = ROp.m(i,1);
AB->M(i,2) = 0.0;
}
} else *AB = ROp;
*XY = Fill(n,2,0.0);
if( INZEE == FFALSE ){
// take complex conjugate for ifft
for( int i=1; i<=n; i++ ) AB->M(i,2) = -AB->m(i,2);
}
do
{
int now, b1;
for (;;){
if (next < nextmx) now = prime[next];
b1 = before / now;
if (b1 * now == before) break;
next++;
now += 2;
}
before = b1;
if (inzee) fftstep(*AB, *XY, after, now, before);
else fftstep(*XY, *AB, after, now, before);
inzee = (inzee == TTRUE) ? FFALSE : TTRUE;
after *= now;
}
while (before != 1);
if ( inzee == TTRUE ) *XY = *AB;
// divide by n for ifft
if ( INZEE == FFALSE) *XY = (*XY)/((double) n);
strtype newname = ( INZEE == TTRUE ) ? "fft( " : "ifft(";
newname = newname + ROp.Getname(ROp) + ")";
XY->Nameit( newname );
Dispatch->Push( *XY );
delete XY;
delete AB;
return Dispatch->DecReturn();
}
//////////////////// reshaping functions
VMatrix& Vec( VMatrix& ROp )
{ // send columns of ROp to a vector
ROp.Garbage("Vec");
long lrc = ((long) ROp.r)*((long) ROp.c);
if (lrc >= 32768 || lrc < 1)
Dispatch->Nrerror("Vec: vec produces invalid indices");
int r = ROp.r*ROp.c;
int c = 1;
VMatrix *temp = new VMatrix("t",r,c);
int cnter=1;
for( int j=1; j<=ROp.c; j++)
for( int i=1; i<=ROp.r; i++) temp->M(cnter++,1) = ROp.m(i,j);
strtype newname = "vec(";
newname = newname + ROp.Getname(ROp) + ")";
temp->Nameit( newname );
Dispatch->Push( *temp );
delete temp;
return Dispatch->ReturnMat();
}
VMatrix& Vecdiag( VMatrix& ROp )
{ // Extract the diagonal from a square matrix and put in a vector
ROp.Garbage("Vecdiag");
if( ROp.r != ROp.c )
Dispatch->Nrerror("Vecdiag: ROp is not square");
VMatrix *temp = new VMatrix( "vdiag(", ROp.r, 1);
for( int i=1; i<=ROp.r; i++) temp->M(i,1) = ROp.m(i,i);
strtype newname = "vdiag(";
newname = newname + ROp.Getname(ROp) + ")";
temp->Nameit( newname );
Dispatch->Push( *temp );
delete temp;
return Dispatch->ReturnMat();
}
VMatrix& Diag( VMatrix& ROp )
{ // make a diagonal matrix from a vector or the principal diagonal of
// a square matrix, off diagonal elements are zero
ROp.Garbage("Diag");
if( ROp.r != ROp.c && ROp.c != 1)
Dispatch->Nrerror("Diag: ROp is not square or is not a column vector");
Dispatch->Inclevel();
VMatrix *temp = new VMatrix;
*temp = Fill( ROp.r, ROp.r, 0.0);
int rr = ROp.r;
int cc = ROp.c;
for( int i=1; i<=rr; i++)
temp->M(i,i) = ( rr==cc ) ? ROp.m(i,i) : ROp.m(i,1);
strtype newname = "diag(";
newname = newname + ROp.Getname(ROp) + ")";
temp->Nameit( newname );
Dispatch->Push( *temp );
delete temp;
return Dispatch->DecReturn();
}
VMatrix& Shape( VMatrix& ROp, int nrows )
{ // reshape a matrix into n rows, nrows must divide r*c without a
// remainder
ROp.Garbage("Shape");
long nr = (long) nrows;
long lr = (long) ROp.r;
long lc = (long) ROp.c;
if( lr*lc % nr )
Dispatch->Nrerror("Shape: nrows divides r*c with a remainder");
Dispatch->Inclevel();
VMatrix *temp = new VMatrix;
*temp = ROp;
long lrc = (lr*lc) / nr;
if ( nr >= 32768 || nr < 1 || lrc >= 32768 || lrc < 1 )
Dispatch->Nrerror("Shape: reshape produces invalid indices");
temp->r = nrows;
temp->c = (int) lrc;
strtype newname = "shape(";
newname = newname + ROp.Getname(ROp) + ")";
temp->Nameit( newname );
Dispatch->Push( *temp );
delete temp;
return Dispatch->DecReturn();
}
///////////////////////////// summation functions // maxs and mins
//// typedef enum margins { ALL, ROWS, COLUMNS } margins;
VMatrix& Sum( VMatrix& ROp, margins marg )
{ // sum(ROp, ALL) returns 1x1
// sum(ROp, ROWS) returns 1xc
// sum(ROp, COLUMNS) returns cx1
ROp.Garbage("Sum");
int r,c;
double sum;
switch( marg ){
case ALL: r = 1; c=1; break;
case ROWS: r=1; c=ROp.c; break;
case COLUMNS: r=ROp.r; c=1; break;
default: Dispatch->Nrerror("Sum: invalid margin specification");
}
VMatrix *temp = new VMatrix("t",r,c);
switch( marg ){
case ALL: sum = 0.0;
for( int i=1; i<=ROp.r; i++ )
for (int j=1; j<=ROp.c; j++) sum += ROp.m(i,j);
temp->M(1,1) = sum;
break;
case ROWS:for( j=1; j<=c; j++ ){
sum = 0.0;
for (int i=1; i<=ROp.r; i++) sum += ROp.m(i,j);
temp->M(1,j) = sum;
}
break;
case COLUMNS:for( i=1; i<=r; i++ ){
sum = 0.0;
for (int j=1; j<=ROp.c; j++) sum += ROp.m(i,j);
temp->M(i,1) = sum;
}
break;
}
strtype newname = "sum(";
newname = newname + ROp.Getname(ROp) + ")";
temp->Nameit( newname );
Dispatch->Push( *temp );
delete temp;
return Dispatch->ReturnMat();
}
VMatrix& Sumsq( VMatrix& ROp, margins marg )
{ // sumsq(ROp, ALL) returns 1x1
// sumsq(ROp, ROWS) returns 1xc
// sumsq(ROp, COLUMNS) returns cx1
ROp.Garbage("Sum");
int r,c;
double sum;
switch( marg ){
case ALL: r = 1; c=1; break;
case ROWS: r=1; c=ROp.c; break;
case COLUMNS: r=ROp.r; c=1; break;
default: Dispatch->Nrerror("Sumsq: invalid margin specification");
}
VMatrix *temp = new VMatrix("t",r,c);
switch( marg ){
case ALL: sum = 0.0;
for( int i=1; i<=ROp.r; i++ )
for (int j=1; j<=ROp.c; j++) sum += ROp.m(i,j)*ROp.m(i,j);
temp->M(1,1) = sum;
break;
case ROWS:for( j=1; j<=c; j++ ){
sum = 0.0;
for (int i=1; i<=ROp.r; i++) sum += ROp.m(i,j)*ROp.m(i,j);
temp->M(1,j) = sum;
}
break;
case COLUMNS:for( i=1; i<=r; i++ ){
sum = 0.0;
for (int j=1; j<=ROp.c; j++) sum += ROp.m(i,j)*ROp.m(i,j);
temp->M(i,1) = sum;
}
break;
}
strtype newname = "sumsq(";
newname = newname + ROp.Getname(ROp) + ")";
temp->Nameit( newname );
Dispatch->Push( *temp );
delete temp;
return Dispatch->ReturnMat();
}
VMatrix& Cusum( VMatrix& ROp)
{ // cumulative sum along rows
ROp.Garbage( "Cusum");
VMatrix *temp = new VMatrix("t",ROp.r, ROp.c);
double sum = 0.0;
for( int i=1; i <= ROp.r; i++){
for( int j=1; j <= ROp.c; j++){
sum += ROp.m(i,j);
temp->M(i,j) = sum;
}
}
strtype newname = "cusum(";
newname = newname + ROp.Getname(ROp) + ")";
temp->Nameit( newname );
Dispatch->Push( *temp );
delete temp;
return Dispatch->ReturnMat();
}
VMatrix& Mmax( VMatrix& ROp, margins marg )
{ // Mmax(ROp, ALL) returns 3x1
// Mmax(ROp, ROWS) returns 3xc
// Mmax(ROp, COLUMNS) returns cx3
ROp.Garbage("Sum");
int r,c;
switch( marg ){
case ALL: r = 3; c=1; break;
case ROWS: r=3; c=ROp.c; break;
case COLUMNS: r=ROp.r; c=3; break;
default: Dispatch->Nrerror("Mmax: invalid margin specification");
}
VMatrix *temp = new VMatrix("t",r,c);
switch( marg ){
case ALL: double mmax = ROp.m(1,1);
int maxr = 1, maxc=1;
for( int i=1; i<=ROp.r; i++ )
for (int j=1; j<=ROp.c; j++)
mmax = (mmax < ROp.m(i,j))?
maxr=i, maxc = j, ROp.m(i,j) : mmax;
temp->M(1,1) = (double) maxr;
temp->M(2,1) = (double) maxc;
temp->M(3,1) = mmax;
break;
case ROWS:for( j=1; j<=c; j++ ){
double mmax = ROp.m(1,j);
int maxr = 1; maxc = j;
for ( i=1; i<=ROp.r; i++)
mmax = (mmax < ROp.m(i,j))? maxr = i, ROp.m(i,j):mmax;
temp->M(1,j) = (double) maxr;
temp->M(2,j) = (double) maxc;
temp->M(3,j) = mmax;
}
break;
case COLUMNS:for( i=1; i<=r; i++ ){
double mmax = ROp.m(i,1);
int maxr = i, maxc = 1;
for ( j=1; j<=ROp.c; j++)
mmax = (mmax < ROp.m(i,j))? maxc = j, ROp.m(i,j):mmax;
temp->M(i,1) = (double) maxr;
temp->M(i,2) = (double) maxc;
temp->M(i,3) = mmax;
}
break;
}
strtype newname = "max(";
newname = newname + ROp.Getname(ROp) + ")";
temp->Nameit( newname );
Dispatch->Push( *temp );
delete temp;
return Dispatch->ReturnMat();
}
VMatrix& Mmin( VMatrix& ROp, margins marg )
{ // Mmin(ROp, ALL) returns 3x1
// Mmin(ROp, ROWS) returns 3xc
// Mmin(ROp, COLUMNS) returns cx3
ROp.Garbage("Sum");
int r,c;
switch( marg ){
case ALL: r = 3; c=1; break;
case ROWS: r=3; c=ROp.c; break;
case COLUMNS: r=ROp.r; c=3; break;
default: Dispatch->Nrerror("Mmin: invalid margin specification");
}
VMatrix *temp = new VMatrix("t",r,c);
switch( marg ){
case ALL: double mmin = ROp.m(1,1);
int maxr = 1, maxc = 1;
for( int i=1; i<=ROp.r; i++ )
for (int j=1; j<=ROp.c; j++)
mmin = (mmin > ROp.m(i,j))?
maxr = i, maxc = j, ROp.m(i,j):mmin;
temp->M(1,1) = (double) maxr;
temp->M(2,1) = (double) maxc;
temp->M(3,1) = mmin;
break;
case ROWS:for( j=1; j<=c; j++ ){
double mmin = ROp.m(1,j);
int maxr = 1, maxc = j;
for (int i=1; i<=ROp.r; i++)
mmin = (mmin > ROp.m(i,j))? maxr=i, ROp.m(i,j):mmin;
temp->M(1,j) = (double) maxr;
temp->M(2,j) = (double) maxc;
temp->M(3,j) = mmin;
}
break;
case COLUMNS:for( i=1; i<=r; i++ ){
double mmin = ROp.m(i,1);
int maxr = i, maxc = 1;
for (int j=1; j<=ROp.c; j++)
mmin = (mmin > ROp.m(i,j))? maxc=j, ROp.m(i,j):mmin;
temp->M(i,1) = (double) maxr;
temp->M(i,2) = (double) maxc;
temp->M(i,3) = mmin;
}
break;
}
strtype newname = "min(";
newname = newname + ROp.Getname(ROp) + ")";
temp->Nameit( newname );
Dispatch->Push( *temp );
delete temp;
return Dispatch->ReturnMat();
}
//////////////////////////////// elemenatary row and column operations
////////////////// note these functions operate directly on ROp
void Crow( VMatrix& ROp, int row, double c)
{ // multiply a row by a constant
ROp.Garbage("Crow");
if( row < 1 || row > ROp.r )
Dispatch->Nrerror("Crow: row index out of range");
for( int i=1; i<=ROp.c; i++) ROp.M(row, i) = c*ROp.m(row,i);
return;
}
void Srow( VMatrix &ROp, int row1, int row2)
{ // swap rows
ROp.Garbage("Srow");
if( row1 < 1 || row1 > ROp.r || row2 < 1 || row2 > ROp.r)
Dispatch->Nrerror("Srow: row index out of range");
double tmp=0;
for( int i=1; i<=ROp.c; i++){
tmp = ROp.m( row1, i);
ROp.M(row1, i) = ROp.m(row2, i);
ROp.M(row2, i) = tmp;
}
return;
}
void Lrow( VMatrix &ROp, int row1, int row2, double c)
{ // add c*r1 to r2
ROp.Garbage("Srow");
if( row1 < 1 || row1 > ROp.r || row2 < 1 || row2 > ROp.r)
Dispatch->Nrerror("Lrow: row index out of range");
for( int i=1; i<=ROp.c; i++)
ROp.M( row2, i) = ROp.m(row2,i) + c*ROp.m(row1,i);
return;
}
void Ccol( VMatrix& ROp, int col, double c)
{ // multiply a col by a constant
ROp.Garbage("Ccol");
if( col < 1 || col > ROp.c )
Dispatch->Nrerror("Ccol: col index out of range");
for( int i=1; i<=ROp.r; i++) ROp.M(i, col) = c*ROp.m(i,col);
return;
}
void Scol( VMatrix &ROp, int col1, int col2)
{ // swap cols
ROp.Garbage("Scol");
if( col1 < 1 || col1 > ROp.c || col2 < 1 || col2 > ROp.c)
Dispatch->Nrerror("Scol: col index out of range");
double tmp=0;
for( int i=1; i<=ROp.r; i++){
tmp = ROp.m( i, col1);
ROp.M(i, col1) = ROp.m(i, col2);
ROp.M(i, col2) = tmp;
}
return;
}
void Lcol( VMatrix &ROp, int col1, int col2, double c)
{ // add c*c1 to c2
ROp.Garbage("Scol");
if( col1 < 1 || col1 > ROp.c || col2 < 1 || col2 > ROp.c)
Dispatch->Nrerror("Lcol: col index out of range");
for( int i=1; i<=ROp.r; i++)
ROp.M( i, col2) = ROp.m(i, col2) + c*ROp.m(i, col1);
return;
}